<?php
declare (strict_types = 1);

namespace app\index;

use app\common\model\system\Menu;
use app\common\model\system\Setting;
use think\App;
use think\Exception;
use think\exception\ValidateException;
use think\facade\View;
use think\Model;
use think\Validate;
use app\index\model\Category;
use app\common\utils\facade\LunarUtil;
use think\facade\Cache;

/**
 * 控制器基础类
 */
abstract class BaseController
{

    /**
     * 当前控制器所用到的模型容器
     */
    protected $models = [];


    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

    /**
     * 构造方法
     * @access public
     * @param  App  $app  应用对象
     */
    public function __construct(App $app)
    {
        $this->app     = $app;
        $this->request = $this->app->request;

        if(!$this->request->isAjax())
            $this->initialize();
    }

    private function initialize(){


        //*主导航
        $mainNav = $this->getMainNavs();

        //*次导航
        $secNav  = $this->getSecNav();

        //*用户
        $user = app()->user->getIdentity();

        //*日期
        $date = $this->getDate();

        //*元数据
        $meta = $this->getMetaData();



        View::assign([

            'mainNav'   =>      $mainNav,
            'user'      =>      $user,
            'secNav'    =>      $secNav,
            'date'      =>      $date,
            'meta'      =>      $meta
        ]);
    }

    //获取主导航数据
    private function getMainNavs(){
        return Menu::getMainNavs();
    }

    //获取元数据
    private function getMetaData(){
        if (!$metaData = Cache::get('meta_data')){

            $metaData = Setting::findOrEmpty(1);

            Cache::set('meta_data', $metaData, 12 * 60);
        }
        return $metaData;
    }

    /**
     * #农历转阴历
     * @return array|mixed
     * @throws \Exception
     */
    private function getDate(){

        if(!$date = Cache::get('lunar_date')){
            $lunar = LunarUtil::convertSolarToLunar(date('Y'),date('m'),date('d'));
            $date = [
                'date'    => date("m月d日.",time()),
                'en_date' => strftime("%B %d."),
                'cn_date' => '农历'.$lunar[1].$lunar[2],
            ];


            //设置缓存
            $expre = new \DateTime(date('Y-m-d 00:00:00', strtotime('+1 day')));
            Cache::set('lunar_date', $date, $expre);
        }
        return $date;

    }

    /**
     * #次导航
     * @return array
     */
    private function getSecNav(){

        if (!$data = Cache::get('sec_nav')){
            $data = Category::getDropList('ASC');

            Cache::set('sec_nav', $data, 12 * 3600);
        }

        //当前控制器
        $currCtrl = strtolower(request()->controller());

        $nav = [];
        foreach ($data as $id => $name){
            $nav[] = [
                'id'=> $id,
                'name' => $name,
                'url' => (string)($currCtrl === 'topic'? url('topic/index',['category_id'=>$id]) : url('category/read',['category_id'=>$id]))
            ];
        }
        return $nav;
    }



    /**
     * 验证数据
     * @access protected
     * @param  array        $data     数据
     * @param  string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     * @param  bool         $batch    是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                list($validate, $scene) = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v     = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }

    /**
     * 从模型容器中获取可用的模型
     * @param string $model
     * @param int|null $id
     * @param array $with
     * @param array $withCount
     * @return mixed
     * @throws Exception
     */
    protected function getModel(string $model, int $id = null, array $with=[], array $withCount=[]){

        if (get_parent_class($model) !== Model::class &&
            get_parent_class(get_parent_class($model)) !== Model::class)
            throw new Exception('传参错误.');

        if (array_key_exists($model, $this->models) && !$id) return $this->models[$model];
        if (!is_null($id)){
            if(! $this->models[$model] = $model::with($with)->withCount($withCount)->find($id) )
                abort(404, '页面不存在.');
        }else{
            $this->models[$model] = new $model();
        }
        return $this->models[$model];
    }

}
